#include <bits/stdc++.h>

#define in read()
#define fi first
#define se second
#define pb push_back
#define rep(i, x, y) for(int i = (x); i <= (y); i++)
#define per(i, x, y) for(int i = (x); i >= (y); i--)

using namespace std;

typedef long long ll;
typedef double db;
typedef vector < int > vec;
typedef pair < int , int > pii;

int read() {
    int x = 0; bool f = 0; char ch = getchar(); while(!isdigit(ch)) f |= ch == '-',ch = getchar();
    while(isdigit(ch)) x = x * 10 + (ch ^ 48),ch = getchar(); return f ? -x : x;
}

const int N = 1e5 + 10;

int fa[N],n,m,siz[N];
ll ans;
vec G[N];
bool vis[N];

inline int gf(int x) { return fa[x] == x ? x : fa[x] = gf(fa[x]); }
inline void merge(int x,int y) {
	x = gf(x); y = gf(y); if(x == y) return;
	if(siz[x] > siz[y]) swap(x,y); fa[x] = y; siz[y] += siz[x]; 
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
#endif
    n = in,m = in;
	rep(i, 1, m) { int a = in,b = in; G[a].pb(b); }
	rep(i, 1, n) fa[i] = i, siz[i] = 1;
	rep(x, 1, n) {
		int lst = -1;
		for(int y : G[x]) { if(~lst) merge(y,lst); lst = y; }
	}
	queue < int > q; rep(i, 1, n) if(siz[gf(i)] > 1) q.push(i),vis[i] = true;
	while(q.size()) {
		int x = q.front(); q.pop();
		for(int y : G[x]) { merge(y,x); if(!vis[y]) q.push(y),vis[y] = true; }
	}
	rep(i, 1, n) if(gf(i) == i) ans += siz[gf(i)] > 1 ? 1ll * siz[gf(i)] * (siz[gf(i)] - 1) : G[i].size();
	printf("%lld\n",ans); return 0;
}
